<script>
export default {
  name: 'Role'
}
</script>
<script setup>
import $API from '@/api/index'
import { useLayoutStore } from '@/store/modules/layout'
import { ElMessage } from 'element-plus'

import { ref, onMounted, computed } from 'vue'

const layoutStore = useLayoutStore()

onMounted(() => {
  reqGetRoleInfo()
  reqRoleMenuAll()
})

// 搜索关键字收集
const keyword = ref('')
const reset = function () {
  layoutStore.changeRefresh()
}

// 角色信息
const roleInfoDataArr = ref([{}])
// 请求角色信息
const reqGetRoleInfo = async function (page = 1) {
  const result = await $API.acl.role.reqGetRoleInfo(page, limit.value, keyword.value)
  if (result?.data?.code === 200) {
    roleInfoDataArr.value = result.data.data.records
    total.value = result.data.data.total

    return 'ok'
  } else {
    return Promise.reject(result?.data?.message)
  }
}

// 角色信息编辑对话框判定
const roleInfoEditor = ref(false)
// 角色信息编辑收集
const roleInfoEditorData = ref({
  remark: '',
  roleName: ''
})
// 角色信息表单DOM
const roleInfoEditorRef = ref()
// 角色信息表单在自定义校验规则
const validateRoleName = function (rule, value, cb) {
  if (value.length === 0) {
    cb(new Error('名字至少1位'))
  } else {
    cb()
  }
}
const roleInfoEditorValidate = {
  roleName: [{ required: true, validator: validateRoleName, trigger: 'change' }]
}
// 打开角色信息编辑对话框
const openRoleInfoEditor = function (row = {}) {
  Object.assign(roleInfoEditorData.value, row)
  roleInfoEditor.value = true
}
// 关闭角色信息编辑对话框
const closeRoleInfoEditor = function () {
  roleInfoEditorRef.value.resetFields()
  roleInfoEditorData.value = {
    remark: '',
    roleName: ''
  }
  roleInfoEditor.value = false
}
// 保存角色信息编辑对话框
const saveRoleInfoEditor = async function (formRef) {
  if (!formRef) return
  try {
    await formRef.validate()
    const result = await $API.acl.role.reqSaveRoleInfo(roleInfoEditorData.value)
    if (result?.data?.code === 200) {
      ElMessage.success(roleInfoEditorData.value.id ? '更新角色成功' : '添加角色成功')
      reqGetRoleInfo(page.value)
      // 关闭对话框
      closeRoleInfoEditor()

      return 'ok'
    } else {
      return Promise.reject(result?.data?.message)
    }
  } catch (error) {
    typeof error === 'object'
      ? ElMessage.error(
          roleInfoEditorData.value.id ? '更新角色失败' : '添加角色失败' + '，请检查表单项'
        )
      : ElMessage.error(roleInfoEditorData.value.id ? '更新角色失败' : '添加角色失败' + error)
  }
}

// 分配角色菜单抽屉判定
const setRoleEditor = ref(false)
// 分配角色菜单收集
const defaultProps = {
  children: 'children',
  label: 'name'
}
// tree组件的DOM
const roleTreeRef = ref()
// 全部菜单数组
const menuAll = ref([])
// 角色对应菜单数组
const roleMenuInfo = ref({})
// 角色选中的对应菜单数组
const roleMenuArrComputed = ref([])
// 获取角色选中对应菜单辅助函数
const getSelectMenuByRole = function (roleMenuData, result = []) {
  roleMenuData.map(item => {
    // 如果有children，继续遍历
    if (Array.isArray(item.children)) {
      if (item.select) result.push(item.id)
      getSelectMenuByRole(item.children, result)
    } else {
      if (item.select) result.push(item.id)
    }
  })
  return result
}
// 请求分配角色菜单抽屉
const reqRoleMenuAll = async function () {
  // 发请求
  const result = await $API.acl.role.reqGetMenuAll()

  if (result?.data?.code === 200) {
    menuAll.value = result.data.data

    return 'ok'
  } else {
    return Promise.reject(result?.data?.message)
  }
}
// 打开分配角色菜单抽屉
const openRoleMenuEditor = async function (row) {
  // 打开抽屉
  setRoleEditor.value = true
  // 发请求
  const result = await $API.acl.role.reqGetMenuByRoleId(row.id)

  if (result?.data?.code === 200) {
    Object.assign(roleMenuInfo.value, row)
    roleMenuArrComputed.value = getSelectMenuByRole(result.data)

    return 'ok'
  } else {
    return Promise.reject(result?.data?.message)
  }
}
// 关闭分配角色菜单抽屉
const closeRoleMenuEditor = function () {
  roleMenuInfo.value = []
  roleMenuArrComputed.value = []
  roleTreeRef.value.setCheckedNodes([])
  setRoleEditor.value = false
}
// 保存分配角色菜单菜单抽屉
const saveSetRoleEditor = async function (row) {
  const data = {
    roleId: roleMenuInfo.value.id,
    permissionId: roleTreeRef.value.getCheckedKeys()
  }
  const result = await $API.acl.role.reqSaveRoleMenu(data)
  if (result?.data?.code === 200) {
    reqGetRoleInfo(page.value)
    closeRoleMenuEditor()
    ElMessage.success('分配职位菜单成功')

    return 'ok'
  } else {
    ElMessage.error('分配职位菜单失败')
    return Promise.reject(result?.data?.message)
  }
}
// 确定删除角色事件
const removeRoleByRoleIdConfirm = async function (roleId) {
  const result = await $API.acl.role.reqRemoverByID(roleId)
  if (result?.data?.code === 200) {
    reqGetRoleInfo(
      roleInfoDataArr.value.length === 1 && page.value > 1 ? page.value - 1 : page.value
    )
    ElMessage.success('删除成功')

    return 'ok'
  } else {
    ElMessage.error('删除失败')
    return Promise.reject(result?.data?.message)
  }
}

// 分页器
// 当前页码
const page = ref(1)
// 每页条数
const limit = ref(10)
// 总条数
const total = ref(0)
// 没有条数变化后的回调函数
const handleSizeChange = function () {
  reqGetRoleInfo()
}
// 页码改变后的回调函数
const handleCurrentChange = function () {
  reqGetRoleInfo(page.value)
}
</script>

<template>
  <div>
    <!-- 搜索框 -->
    <el-card>
      <el-form class="form">
        <el-form-item label="角色名称">
          <el-input
            style="width: 250px"
            placeholder="请输入角色名称"
            v-model="keyword"
          />
        </el-form-item>
        <el-form-item>
          <el-button
            type="primary"
            :disabled="!keyword"
            @click="reqGetRoleInfo()"
            >搜索</el-button
          >
          <el-button @click="reset">重置</el-button>
        </el-form-item>
      </el-form>
    </el-card>

    <!-- 角色表格 -->
    <el-card class="marginTop20px">
      <!-- 按钮 -->
      <div class="tableBtn">
        <el-button
          type="primary"
          @click="openRoleInfoEditor()"
          v-has="'btn.Role.add'"
        >
          添加职位
        </el-button>
      </div>

      <!-- 表格 -->
      <el-table
        :data="roleInfoDataArr"
        class="marginTop20px"
        border
        stripe
      >
        <el-table-column
          label="#"
          align="center"
          width="80"
        >
          <template #="{ $index }">
            <span>{{ $index + 1 }}</span>
          </template>
        </el-table-column>
        <el-table-column
          prop="id"
          label="id"
          align="center"
          width="80"
          show-overflow-tooltip
        />
        <el-table-column
          prop="roleName"
          label="职位名称"
          min-width="150"
          show-overflow-tooltip
        />
        <el-table-column
          prop="createTime"
          label="创建时间"
          min-width="150"
          show-overflow-tooltip
        />
        <el-table-column
          prop="updateTime"
          label="更新时间"
          min-width="150"
          show-overflow-tooltip
        />
        <el-table-column
          label="操作"
          align="center"
          min-width="350"
        >
          <template #="{ row }">
            <el-button
              type="primary"
              icon="User"
              @click="openRoleMenuEditor(row)"
              v-has="'btn.Role.assgin'"
            >
              分配权限
            </el-button>
            <el-button
              type="primary"
              icon="Edit"
              @click="openRoleInfoEditor(row)"
              v-has="'btn.Role.update'"
            >
              编辑
            </el-button>

            <el-popconfirm
              :title="`确定要删除角色 ${row.roleName} 吗？`"
              @confirm="removeRoleByRoleIdConfirm(row.id)"
            >
              <template #reference>
                <el-button
                  type="primary"
                  icon="Delete"
                  v-has="'btn.Role.remove'"
                >
                  删除
                </el-button>
              </template>
            </el-popconfirm>
          </template>
        </el-table-column>
      </el-table>

      <!-- 分页器 -->
      <el-pagination
        class="marginTop20px"
        v-model:current-page="page"
        v-model:page-size="limit"
        :page-sizes="[10, 20, 30, 40]"
        :total="total"
        layout="prev, pager, next, jumper, ->, sizes, total,"
        @size-change="handleSizeChange"
        @current-change="handleCurrentChange"
      />
    </el-card>

    <!-- 添加&编辑角色抽屉 -->
    <el-dialog
      v-model="roleInfoEditor"
      :title="roleInfoEditorData.id ? '修改角色' : '添加角色'"
      direction="rtl"
      @closed="closeRoleInfoEditor()"
      width="500"
    >
      <el-form
        label-width="80px"
        :model="roleInfoEditorData"
        ref="roleInfoEditorRef"
        :rules="roleInfoEditorValidate"
      >
        <el-form-item
          label="角色名称"
          prop="roleName"
        >
          <el-input
            v-model="roleInfoEditorData.roleName"
            placeholder="请填写角色名称"
          />
        </el-form-item>
      </el-form>
      <template #footer>
        <el-button @click="closeRoleInfoEditor()">取消</el-button>
        <el-button
          type="primary"
          @click="saveRoleInfoEditor(roleInfoEditorRef)"
        >
          确定
        </el-button>
      </template>
    </el-dialog>

    <!-- 分配角色抽屉 -->
    <el-drawer
      v-model="setRoleEditor"
      title="分配权限"
      direction="rtl"
      @closed="closeRoleMenuEditor()"
    >
      <el-tree
        ref="roleTreeRef"
        style="max-width: 600px"
        :data="menuAll"
        show-checkbox
        node-key="id"
        default-expand-all
        :default-checked-keys="roleMenuArrComputed"
        :props="defaultProps"
        :check-strictly="true"
      />
      <template #footer>
        <el-button @click="closeRoleMenuEditor()">取消</el-button>
        <el-button
          type="primary"
          @click="saveSetRoleEditor()"
        >
          确定
        </el-button>
      </template>
    </el-drawer>
  </div>
</template>

<style scoped lang="scss">
.form {
  display: flex;
  justify-content: space-between;
  align-items: center;
  .el-form-item {
    margin-bottom: 0;
  }
}
</style>
